<!-- 角色管理页面 -->
<template>
    <!-- 单根，全屏 -->
    <div class="full-div">
        <!-- 占屏50% -->
        <div style="display: inline-block; width: 60%;">
            <!-- 操作栏 -->
            <el-row style="padding: 5px 0px;">
                <el-button type="primary" @click="bindPermission" plain>绑定权限</el-button>
                <el-button type="primary" @click="addRole" plain>添加角色</el-button>
            </el-row>
            <!-- 角色表 -->
            <el-table ref="roleTableRef" :data="roleData" highlight-current-row @current-change="handleCurrentChange"
                      v-loading="roleTableLoading" stripe>
                <el-table-column prop="id" label="id" width="50"/>
                <el-table-column prop="name" label="名称" width="120"/>
                <el-table-column prop="code" label="标识" width="140"/>
                <el-table-column prop="isBan" label="是否禁用">
                    <template #default="data">
                        <span style="color:green" v-if="!data.row.isBan">否</span>
                        <span style="color:red" v-else>是</span>
                    </template>
                </el-table-column>
                <el-table-column label="操作" width="200" fixed="right">
                    <template #default="data">
                        <el-button link type="primary" size="small" @click="editRole(data.row)">编辑</el-button>
                        <el-button link type="danger" size="small" @click="removeRole(data.row)">删除</el-button>
                    </template>
                </el-table-column>
            </el-table>
        </div>
        <!-- 占屏50% -->
        <div style="display: inline-block; width: 40%;">
            <!-- 操作栏 -->
            <el-row style="padding: 5px 0px;">
                <el-button type="primary" @click="addPermission()" plain>添加权限</el-button>
            </el-row>
            <!-- 权限树 -->
            <el-input v-model="filterText" placeholder="Filter keyword"/>
            <el-scrollbar>
                <el-tree ref="permissionTreeRef" :data="permissionData" :props="treeConfig" lazy :load="loadNode"
                         node-key="id" :filter-node-method="filterNode" show-checkbox
                         :default-expanded-keys="expendKeys"
                         v-loading="permissionTreeLoading" :expand-on-click-node="false">
                    <template #default="{ node, data }">
                        <span class="custom-tree-node">
                            <div>
                                <span style="color:red" v-if="data.isBan">{{ data.name }}({{ data.code }})</span>
                                <span v-else>[{{data.sort}}]{{ data.name }}({{ data.code }})</span>
                            </div>
                            <span>
                                <el-button v-if="data.type != PermissionType.permission" link type="primary"
                                           size="small"
                                           @click="addPermission(data)">添加权限</el-button>
                                <el-button link type="primary" size="small"
                                           @click="editPermission(data)">编辑</el-button>
                                <el-button link type="danger" size="small"
                                           @click="removePermission(node, data)">删除</el-button>
                            </span>
                        </span>
                    </template>
                </el-tree>
            </el-scrollbar>
        </div>
        <!-- 角色表单 -->
        <el-dialog v-model="roleDialogVisible" :title="roleDialogTitle" width="400px" draggable>
            <el-form v-if="roleDialogForm" :model="roleDialogForm" label-width="auto">
                <el-form-item label="id">
                    <el-input v-model="roleDialogForm.id"/>
                </el-form-item>
                <el-form-item label="名称">
                    <el-input v-model="roleDialogForm.name"/>
                </el-form-item>
                <el-form-item label="标识">
                    <el-input v-model="roleDialogForm.code"/>
                </el-form-item>
                <el-form-item label="描述">
                    <el-input v-model="roleDialogForm.description"/>
                </el-form-item>
                <el-form-item label="状态">
                    <el-radio-group v-model="roleDialogForm.isBan">
                        <el-radio :label="false">正常</el-radio>
                        <el-radio :label="true">禁用</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="排序">
                    <el-input v-model="roleDialogForm.sort"/>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="roleDialogVisible = false">取消</el-button>
                <el-button @click="roleDialogFormReset">重置</el-button>
                <el-button type="primary" @click="roleDialogFormSubmit">
                    提交
                </el-button>
            </template>
        </el-dialog>
        <!-- 权限表单 -->
        <el-dialog v-model="permissionDialogVisible" :title="permissionDialogTitle" width="400px" draggable>
            <el-form v-if="permissionDialogForm" :model="permissionDialogForm" label-width="auto">
                <!-- <el-form-item label="id">
                    <el-input v-model="permissionDialogForm.id" />
                </el-form-item> -->
                <el-form-item label="父节点id">
                    <el-input v-model="permissionDialogForm.pid"/>
                </el-form-item>
                <el-form-item label="名称">
                    <el-input v-model="permissionDialogForm.name"/>
                </el-form-item>
                <el-form-item label="类型">
                    <el-radio-group v-model="permissionDialogForm.type">
                        <!-- <el-radio :label=PermissionType.content>目录</el-radio> -->
                        <el-radio :label=PermissionType.menu>菜单</el-radio>
                        <el-radio :label=PermissionType.permission>权限</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="权限值">
                    <el-input v-model="permissionDialogForm.code"/>
                </el-form-item>
                <el-form-item label="状态">
                    <el-radio-group v-model="permissionDialogForm.isBan">
                        <el-radio :label="false">启用</el-radio>
                        <el-radio :label="true">禁用</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="排序">
                    <el-input v-model="permissionDialogForm.sort"/>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="permissionDialogVisible = false">取消</el-button>
                <el-button @click="permissionDialogFormReset">重置</el-button>
                <el-button type="primary" @click="permissionDialogFormConfirm">
                    提交
                </el-button>
            </template>
        </el-dialog>

    </div>
</template>

<script setup lang="ts">
import {ElMessage, ElMessageBox} from 'element-plus';
import {myAxios} from '../assets/ts/my-axios'
import {Ref, onMounted, ref, watch} from 'vue';
import type Node from 'element-plus/es/components/tree/src/model/node'
import {TreeNodeData} from 'element-plus/es/components/tree-v2/src/types'
import {PermissionInfo, PermissionType, RoleInfo} from '../assets/ts/role-manager'


// 挂载时调用
onMounted(() => {
    loadPermission()
    loadRole()
})

// ===================================== 权限树 ==========================================

// 树节点属性 el-tree 需要
const treeConfig = {
    label: 'id',
    children: 'childPermission',
    isLeaf: isLeaf
}

// 树
const permissionData: Ref<Array<PermissionInfo>> = ref([])

// 加载树
function loadPermission() {
    permissionTreeLoading.value = true
    myAxios.get('/permi/selectMenu')
        .then((response: any) => {
            if (response.data.code == 0) {
                permissionData.value = response.data.data
            } else {
                ElMessage.error(response.data.message)
            }
        }).finally(() => {
        permissionTreeLoading.value = false
    })
}

// 加载节点
function loadNode(node: Node, resolve: Function) {
    console.log('loadNode:' + node.data.id)
    if (node.data.id) {
        myAxios.get('/permi/selectPermi', {params: {id: node.data.id}})
            .then((response) => {
                if (response.data.code == -1) {
                    ElMessage.error(response.data.message)
                } else {
                    return resolve(response.data.data)
                }
            })
    }
}

// 判断是否叶子节点
function isLeaf(data: TreeNodeData, _node: Node) {
    return data.type == PermissionType.permission
}

// 筛选变量
const filterText = ref('')
// @ts-ignore
const permissionTreeRef = ref<InstanceType<typeof ElTree>>()

// 展开的节点
const expendKeys = ref<Array<any>>([])

// 监听筛选框
watch(filterText, (val) => {
    permissionTreeRef.value!.filter(val)
})

// 筛选处理
const filterNode = (value: string, data: TreeNodeData) => {
    if (!value) return true
    return data.name.includes(value)
}


// 删除权限
function removePermission(node: Node, data: PermissionInfo) {
    ElMessageBox.confirm(
        '是否确认删除权限:' + data.name,
        '删除权限',
        {
            confirmButtonText: '确认',
            cancelButtonText: '取消',
            type: 'warning',
        }
    ).then(() => {
        // 删除权限
        myAxios.post('/permi/remove', {permissionId: data.id}, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
            .then((response) => {
                    if (response.data.code == 0) {
                        permissionTreeRef.value!.remove(node)
                    } else {
                        ElMessage.error(response.data.message)
                    }
                }
            )
    }).catch((e: any) => {
        console.log("取消 e:" + e)
    })
}

// ===================================== 权限表单 ==========================================

enum PermissionDialogType { add, edit }

const permissionDialogVisible = ref(false)
const permissionDialogTitle = ref('')
const permissionDialogType = ref<PermissionDialogType>(PermissionDialogType.add)
const permissionDialogForm = ref<PermissionInfo>()
let permissionDialogFormSource: PermissionInfo

// 添加权限
function addPermission(parentPermission?: PermissionInfo) {
    // 类型为添加
    permissionDialogType.value = PermissionDialogType.add
    permissionDialogTitle.value = '添加应用'
    // 表单初始化
    permissionDialogFormSource = {
        id: 0,
        pid: parentPermission ? parentPermission.id : 0,
        name: parentPermission ? parentPermission.name + '_0' : '',
        type: PermissionType.permission,
        code: '',
        isBan: false,
        sort: 999,
    }
    permissionDialogFormReset()
    // 展示面板
    permissionDialogVisible.value = true
}

// 编辑权限
function editPermission(permission: PermissionInfo) {
    // 类型为编辑
    permissionDialogType.value = PermissionDialogType.edit
    permissionDialogTitle.value = '编辑应用'
    // 表单初始化
    permissionDialogFormSource = {...permission}
    permissionDialogFormReset()
    // 展示面板
    permissionDialogVisible.value = true

}

// 重置权限表单
function permissionDialogFormReset() {
    permissionDialogForm.value = permissionDialogFormSource
}

// 权限表单提交
function permissionDialogFormConfirm() {
    let apiUrl =
        permissionDialogType.value == PermissionDialogType.add ? '/permi/add'
            : permissionDialogType.value == PermissionDialogType.edit ? '/permi/edit'
                : ''
    myAxios.post(apiUrl, permissionDialogForm.value)
        .then((response) => {
            if (response.data.code == 0) {
                ElMessage.success('提交成功')
                permissionDialogVisible.value = false
                loadPermission()
            } else {
                ElMessage.error(response.data.message)
            }
        })
}


// 加载中表示
const permissionTreeLoading = ref(false)


// ===================================== 角色表 ==========================================

// 角色表
const roleData: Ref<RoleInfo[]> = ref([])
const roleTableLoading = ref(false)

// 加载角色表
function loadRole() {
    roleTableLoading.value = true
    myAxios.get('/role/listAll')
        .then((response) => {
            if (response.data.code == 0) {
                roleData.value = response.data.data
            } else {
                ElMessage.error(response.data.message)
            }
        }).catch((err) => {
        console.error(err)
    })
        .finally(() => {
            roleTableLoading.value = false
        })
}


// 当前列表
const currentRow = ref()
// @ts-ignore
const roleTableRef = ref<InstanceType<typeof ElTable>>()

// 选中角色
const handleCurrentChange = (role: RoleInfo | undefined) => {
    currentRow.value = role
    loadRolePermission()
}

// 根据角色id获取权限列表
function loadRolePermission() {
    if (currentRow.value) {
        permissionTreeLoading.value = true
        myAxios.get('/permi/selectByRoleId', {params: {roleId: currentRow.value.id}})
            .then((response) => {
                if (response.data.code == 0) {
                    let expendKeysTemp: String[] = []
                    let checkedKeysTemp: String[] = []
                    response.data.data.forEach((menu: any) => {
                        expendKeysTemp.push(menu.id)
                        if (menu.childPermission.length) {
                            menu.childPermission.forEach((permi: any) => {
                                checkedKeysTemp.push(permi.id)
                            })
                        } else {
                            checkedKeysTemp.push(menu.id)
                        }
                    })
                    expendKeys.value = expendKeysTemp
                    permissionTreeRef.value!.setCheckedKeys(checkedKeysTemp)
                } else {
                    ElMessage.error(response.data.message)
                }
            }).catch((err) => {
            console.error(err)
        }).finally(() => {
                permissionTreeLoading.value = false
            }
        )
    }
}

// 绑定权限
function bindPermission() {
    if (currentRow.value) {
        ElMessageBox.confirm(
            '正在为角色: ' + currentRow.value.name + ' 绑定权限，请确认是否已选择权限',
            '绑定权限',
            {
                confirmButtonText: '确认',
                cancelButtonText: '取消',
                type: 'warning',
            }
        ).then(() => {
            let permissionIds: any = permissionTreeRef.value!.getCheckedKeys()
            let halfPermissionIds: any = permissionTreeRef.value!.getHalfCheckedKeys()
            if (halfPermissionIds.length) {
                permissionIds = permissionIds + "," + halfPermissionIds
            }
            let rbindPermissionParams = new URLSearchParams()
            rbindPermissionParams.set('roleId', currentRow.value.id)
            rbindPermissionParams.set('permissionIds', permissionIds)
            myAxios.post('/permi/allocateByRole', rbindPermissionParams, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
                .then((response) => {
                    if (response.data.code == 0) {
                        ElMessage.success('绑定成功')
                    } else {
                        ElMessage.error(response.data.message)
                    }
                })
        })
    } else {
        ElMessage.error('请先选择角色')
    }
}

// 删除角色
function removeRole(role: RoleInfo) {
    ElMessageBox.confirm(
        '是否确认删除角色:' + role.name,
        '删除角色',
        {
            confirmButtonText: '确认',
            cancelButtonText: '取消',
            type: 'warning',
        }
    ).then(() => {
        myAxios.post('/role/remove', {roleId: role.id}, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
            .then((response) => {
                    if (response.data.code == 0) {
                        roleData.value.splice(role.id)
                    } else {
                        ElMessage.error(response.data.message)
                    }
                }
            )
    }).catch((e: any) => {
        console.log("取消 e:" + e)
    })
}

// ===================================== 角色表单 ==========================================

enum RoleDialogType { add, edit }

const roleDialogVisible = ref(false)
const roleDialogTitle = ref('')
const roleDialogType = ref(RoleDialogType.add)
const roleDialogForm = ref<RoleInfo>()
let roleDialogFormSource: RoleInfo

// 添加角色
function addRole() {
    // 类型为添加
    roleDialogType.value = RoleDialogType.add
    roleDialogTitle.value = '添加角色'
    // 表单初始化
    roleDialogFormSource = {
        id: 0,
        name: '',
        code: '',
        isBan: false,
        description: '',
        sort: 999,
    }
    roleDialogFormReset()
    // 展示面板
    roleDialogVisible.value = true
}

// 编辑角色
function editRole(role: RoleInfo) {
    // 类型为编辑
    roleDialogType.value = RoleDialogType.edit
    roleDialogTitle.value = '编辑角色'
    // 表单初始化
    roleDialogFormSource = {...role}
    roleDialogFormReset()
    // 展示面板
    roleDialogVisible.value = true
}

// 重置角色表单
function roleDialogFormReset() {
    roleDialogForm.value = {...roleDialogFormSource}
}

// 角色表单提交
function roleDialogFormSubmit() {
    let apiUrl =
        roleDialogType.value == RoleDialogType.add ? '/role/add'
            : roleDialogType.value == RoleDialogType.edit ? '/role/edit'
                : ''
    myAxios.post(apiUrl, roleDialogForm.value)
        .then((response) => {
            if (response.data.code == 0) {
                ElMessage.success('提交成功')
                roleDialogVisible.value = false
                loadRole()
            } else {
                ElMessage.error(response.data.message)
            }
        })
}


</script>

<style scoped>
.custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
}
</style>